using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;

namespace DnsService.Utilities
{
    /// <summary>
    /// 网络DNS监控器：在启动和网络变化时枚举每个网卡的DNS服务器，并触发事件。
    /// </summary>
    public class NetworkDnsMonitor : IDisposable
    {
        private bool _started = false;
        private Dictionary<string, List<string>> _lastPerInterface = new();
        private List<string> _lastAggregated = new();

        public event EventHandler<DnsServersUpdatedEventArgs>? DnsServersUpdated;

        /// <summary>
        /// 启动监控（立即执行一次枚举并订阅网络变化事件）。
        /// </summary>
        public void Start()
        {
            if (_started) return;
            _started = true;

            NetworkChange.NetworkAddressChanged += OnNetworkChanged;
            NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged;

            RefreshAndNotify();
        }

        /// <summary>
        /// 停止监控并解除事件订阅。
        /// </summary>
        public void Stop()
        {
            if (!_started) return;
            _started = false;
            try
            {
                NetworkChange.NetworkAddressChanged -= OnNetworkChanged;
                NetworkChange.NetworkAvailabilityChanged -= OnNetworkAvailabilityChanged;
            }
            catch { }
        }

        private void OnNetworkChanged(object? sender, EventArgs e)
        {
            RefreshAndNotify();
        }

        private void OnNetworkAvailabilityChanged(object? sender, NetworkAvailabilityEventArgs e)
        {
            RefreshAndNotify();
        }

        /// <summary>
        /// 获取当前每接口DNS与聚合DNS（不触发事件）。
        /// </summary>
        public (Dictionary<string, List<string>> perInterface, List<string> aggregated) GetCurrentDns()
        {
            return EnumerateDnsServers();
        }

        private void RefreshAndNotify()
        {
            var (perInterface, aggregated) = EnumerateDnsServers();

            // 计算差异
            var added = aggregated.Except(_lastAggregated).ToList();
            var removed = _lastAggregated.Except(aggregated).ToList();

            _lastPerInterface = perInterface;
            _lastAggregated = aggregated;

            DnsServersUpdated?.Invoke(this, new DnsServersUpdatedEventArgs
            {
                PerInterfaceDns = perInterface,
                AggregatedDnsServers = aggregated,
                AddedDnsServers = added,
                RemovedDnsServers = removed
            });
        }

        private (Dictionary<string, List<string>>, List<string>) EnumerateDnsServers()
        {
            var result = new Dictionary<string, List<string>>();
            try
            {
                var nics = NetworkInterface.GetAllNetworkInterfaces()
                    .Where(ni => ni.OperationalStatus == OperationalStatus.Up &&
                                 ni.NetworkInterfaceType != NetworkInterfaceType.Loopback);

                foreach (var ni in nics)
                {
                    var props = ni.GetIPProperties();
                    var dns = props.DnsAddresses.Select(ip => ip.ToString()).Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
                    result[$"{ni.Name}|{ni.NetworkInterfaceType}"] = dns;
                }

                var aggregated = result.Values.SelectMany(v => v).Distinct().ToList();
                return (result, aggregated);
            }
            catch
            {
                return (result, new List<string>());
            }
        }

        public void Dispose()
        {
            Stop();
        }
    }

    /// <summary>
    /// 事件参数：DNS服务器更新信息
    /// </summary>
    public class DnsServersUpdatedEventArgs : EventArgs
    {
        private Dictionary<string, List<string>> _perInterfaceDns = new();
        /// <summary>按网络接口分组的DNS服务器列表（永不为 null）</summary>
        public Dictionary<string, List<string>> PerInterfaceDns { get => _perInterfaceDns; set => _perInterfaceDns = value ?? new(); }

        private List<string> _aggregatedDnsServers = new();
        /// <summary>聚合后的DNS服务器列表（永不为 null）</summary>
        public List<string> AggregatedDnsServers { get => _aggregatedDnsServers; set => _aggregatedDnsServers = value ?? new(); }

        private List<string> _addedDnsServers = new();
        /// <summary>新增检测到的DNS服务器（永不为 null）</summary>
        public List<string> AddedDnsServers { get => _addedDnsServers; set => _addedDnsServers = value ?? new(); }

        private List<string> _removedDnsServers = new();
        /// <summary>移除/不再检测到的DNS服务器（永不为 null）</summary>
        public List<string> RemovedDnsServers { get => _removedDnsServers; set => _removedDnsServers = value ?? new(); }
    }
}